#include "ConsoleServer.h"
#include <QApplication>
#include <QShortcut>
#include <QDebug>

ConsoleServer::ConsoleServer(QObject *parent)
    : QObject(parent)
{
}

ConsoleServer* ConsoleServer::instance()
{
    static ConsoleServer inst;
    return &inst;
}

void ConsoleServer::init(quint16 port)
{
    if (initialized) return;
    initialized = true;

    udpSocket = new QUdpSocket(this);
    udpSocket->bind(QHostAddress::AnyIPv4, port);
    connect(udpSocket, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
    qDebug() << "[Console] UDP listening on port" << port;

    // 默认 help 命令
    registerCommand("help", "显示所有命令及说明", [this](QStringList) {
        QStringList lines;
        lines << "=== Available commands ===";
        const auto keys = commandMap.keys();
        for (const auto &k : keys) {
            lines << QString("%1 - %2").arg(k, commandMap.value(k).help);
        }
        return lines.join("\n");
    });
}

void ConsoleServer::registerCommand(const QString &name, const QString &help,
                                    std::function<QString(QStringList)> func)
{
    commandMap[name] = {help, func};

    // 更新 GUI 控制台补全列表
    if (guiConsole)
        guiConsole->setCommandList(commandMap.keys());
}

void ConsoleServer::onReadyRead()
{
    while (udpSocket->hasPendingDatagrams()) {
        QByteArray datagram;
        datagram.resize(int(udpSocket->pendingDatagramSize()));
        QHostAddress sender;
        quint16 senderPort;
        udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);

        const QString cmdLine = QString::fromUtf8(datagram).trimmed();
        qDebug() << "[Console] Received:" << cmdLine;

        QStringList parts = cmdLine.split(' ', QString::SkipEmptyParts);
        if (parts.isEmpty()) continue;

        const QString cmd = parts.takeFirst();
        QString reply;

        if (commandMap.contains(cmd)) {
            try {
                reply = commandMap[cmd].func(parts);
            } catch (...) {
                reply = "Error: exception during command execution.";
            }
        } else {
            reply = QString("Unknown command: %1\nType 'help' for list.").arg(cmd);
        }

        udpSocket->writeDatagram(reply.toUtf8(), sender, senderPort);
        emit commandExecuted(cmd, reply);
    }
}
void ConsoleServer::showConsole()
{
    if (!guiConsole) return;
    guiConsole->show();
    guiConsole->raise();
    guiConsole->activateWindow();
}

void ConsoleServer::hideConsole()
{
    if (!guiConsole) return;
    guiConsole->hide();
}

void ConsoleServer::toggleConsole()
{
    if (!guiConsole) return;
    guiConsole->setVisible(!guiConsole->isVisible());
}

// ✅ 重新绑定快捷键
void ConsoleServer::attachShortcut(QWidget *target, const QKeySequence &key)
{
    if (!guiConsole) return;

    // 删除旧快捷键
    if (shortcut) {
        shortcut->disconnect();
        shortcut->deleteLater();
        shortcut = nullptr;
    }

    if (!target) target = guiConsole;  // 没传就绑定自己

    shortcut = new QShortcut(key, target);
    QObject::connect(shortcut, &QShortcut::activated, [this]() {
        toggleConsole();
    });

    qDebug() << "[ConsoleServer]" << "快捷键绑定到窗口:" << target << "键位:" << key.toString();
}
void ConsoleServer::enableLocalConsole(bool enabled)
{
    if (!enabled) return;

    if (!guiConsole) {
        guiConsole = new ConsoleWidget();
        guiConsole->hide();

        // ✅ 初次绑定快捷键
        attachShortcut(qApp->activeWindow(), QKeySequence("Ctrl+F12"));

        connect(guiConsole, &ConsoleWidget::commandEntered, [this](const QString &cmd){
            QStringList parts = cmd.split(' ', QString::SkipEmptyParts);
            if (parts.isEmpty()) return;
            QString name = parts.takeFirst();

            QString result;
            if (commandMap.contains(name))
                result = commandMap[name].func(parts);
            else
                result = QString("Unknown command: %1").arg(name);

            guiConsole->appendOutput("> " + cmd);
            guiConsole->appendOutput(result);
            emit commandExecuted(name, result);
        });

        guiConsole->setCommandList(commandMap.keys());
    }
}
